import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ConnectException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Client{
	
	String line_break = "===================================\n";
	String name = "";
	
	Scanner scan;
	Socket s;
	Socket c_s;
	ObjectOutputStream out;
	ObjectInputStream in;
	
	public Client(){
		
		scan = new Scanner(System.in);
	}
	
	public void run(){
		
		int cursor = 0;
		boolean running = true;
		String ip = "";
		int port = -1;
		
		while(running){
			
			printMenu();
			
			cursor = scan.nextInt();
			System.out.println();
			
			try{
					
				switch(cursor){
					
					//Connect to the server
					case 0:{
						
						System.out.print("IP address of the server: ");
						ip = scan.next();
						
						System.out.print("Port to connect to: ");
						
						try{
							
							port = scan.nextInt();
						}
						catch(NumberFormatException e){
							
							System.out.println("ERROR!  You must enter a number.");
							break;
						}
						
						establishConnection(ip, port);
						
						out.writeInt(0);
						out.flush();
						
						if(authenticate()){
							
							System.out.println("**Authentication Successful**");
							System.out.println("Welcome, " + name + "!\n");
						}
						else
						{
							System.out.println("Could not validate your credentials!");
							disconnectConsole();
						}
						
						break;
					}
					//Prints the current user list
					case 1:{
						
						String[] users = null;
						
						try{
							
						out.writeInt(1);
						out.flush();
						
						users = (String[]) in.readObject();
						}
						catch(ClassNotFoundException e){
							
							e.printStackTrace();
						}
						
						if(users != null){
							
							System.out.println("There are currently " + users.length + " users:");
							
							for(int i = 0; i < users.length; i++){
								
								System.out.println("User " + i + ": " + users[i]);
							}
							
							System.out.println(line_break);
						}
						
						break;
					}
					//Send a message
					case 2:{
						
						out.writeInt(2);
						
						//The message target
						System.out.print("Who should this message be sent to?: ");
						out.writeObject(scan.next());
						
						//The clients name
						out.writeObject(name);
						
						//The message content
						System.out.print("What should this message say?:");
						
						scan.useDelimiter("\n");
						out.writeObject(scan.next());
						scan.reset();
						
						out.flush();
						
						if(in.readBoolean())
							System.out.println("**Message Was Sent Successfully**\n");
						else
							System.out.println("**Message Was NOT Sent Successfully**\n");
						
						break;
					}
					//Receive messages
					case 3:{
						
						out.writeInt(3);
						out.writeObject(name);
						out.flush();
						
						String[] messages = null;
						int message_no = -1;
						
						try{
							
							messages = (String[]) in.readObject();
							message_no = in.readInt();
						}
						catch(ClassNotFoundException e){
							
							e.printStackTrace();
						}
						
						if(messages != null){
							
							System.out.println("You have " + message_no + " messages: ");
							
							for(int i = 0; i < message_no; i++){
								
								System.out.println(i + ": " + messages[i]);
							}
						}
						
						System.out.println(line_break);
						
						break;
					}
					//Start chat
					case 4:{
						
						out.writeInt(4);
						break;
					}
					//Enter chat
					case 5:{
						
						out.writeInt(5);
						break;
					}
					//Exit application
					case 6:{
						
						out.writeInt(6);
						
//						DEBUG OUTPUT
//						System.out.println("Client out stream flushing now");
						out.flush();
						
//						DEBUG OUTPUT
//						System.out.println("About to read from input stream...");
						
						//Once the server has acknowledged that the connection is to terminate, then close the connection
						running = in.readBoolean();
						
//						DEBUG OUTPUT
//						System.out.println("Read from input stream! (Value: " + running + ")");
						
						break;
					}
					//Continue execution - incorrect entry
					default:{
						
						System.out.println("Please choose a correct value!");
					}
				}
				
//				DEBUG OUTPUT
//				System.out.println("Client out stream flushing now");
				out.flush();
			}
			catch(IOException e){
				
				e.printStackTrace();
			}
		}
		
		disconnectConsole();
	}
	
	private void establishConnection(String ip, int port){
		
		try{
			
			s = new Socket(ip, port);
			out = new ObjectOutputStream(s.getOutputStream());
			in = new ObjectInputStream(s.getInputStream());
			
			System.out.println("**Connection Successful**\n");
		}
		catch(UnknownHostException e){
			
			System.err.println("You are trying to connect to an unknown host!");
		}
		catch(ConnectException e){
			
			System.err.println("Connection refused!  Start the server first?");
		}
		catch(IOException e){
			
			e.printStackTrace();
		}
		
	}
	
	private void disconnectConsole(){
		
		try{
			
			in.close();
			out.close();
			s.close();
			
			System.out.println("**Disconnected From Server**\n");
		}
		catch(IOException e){
			
			e.printStackTrace();
		}
	}
	
	private boolean authenticate(){
		
		System.out.print("Your name: ");
		
		name = scan.next();
		
		System.out.print("Your password: ");
		
		try{
			
			//Sends the user name and password
			out.writeObject(name);
			out.writeObject(scan.next());
			out.flush();
			
			System.out.println("Authenticating...");
			
			//Returns a validation sent by the server
			return in.readBoolean();
		}
		catch(IOException e){
			
			e.printStackTrace();
		}
		
		return false;
	}
	
	private void printMenu(){
		
		System.out.println("0. Connect To A Server");
		System.out.println("1. Print The Current User List");
		System.out.println("2. Send A Message");
		System.out.println("3. Check Messages");
		System.out.println("4. Start Chat");
		System.out.println("5. Enter Chat");
		System.out.println("6. Exit Application\n");
		System.out.print("Select An Option: ");
	}
	
	public static void main(String[] args){
		
		Client c = new Client();
		c.run();
		
		System.out.println("**Application Exited**");
	}
}